// 版权归 Epic Games, Inc. 所有，保留所有权利。

#include "LyraUIManagerSubsystem.h"

#include "CommonLocalPlayer.h"
#include "Engine/GameInstance.h"
#include "GameFramework/HUD.h"
#include "GameUIPolicy.h"
#include "PrimaryGameLayout.h"

#include UE_INLINE_GENERATED_CPP_BY_NAME(LyraUIManagerSubsystem)

class FSubsystemCollectionBase;

/**
 * 构造函数
 */
ULyraUIManagerSubsystem::ULyraUIManagerSubsystem()
{
}

/**
 * 初始化子系统
 * @param Collection 子系统集合基类引用
 */
void ULyraUIManagerSubsystem::Initialize(FSubsystemCollectionBase& Collection)
{
	Super::Initialize(Collection); // 调用父类初始化

	TickHandle = FTSTicker::GetCoreTicker().AddTicker(FTickerDelegate::CreateUObject(this, &ULyraUIManagerSubsystem::Tick), 0.0f); // 注册Tick委托到核心Ticker
}

/**
 * 反初始化子系统
 */
void ULyraUIManagerSubsystem::Deinitialize()
{
	Super::Deinitialize(); // 调用父类反初始化

	FTSTicker::GetCoreTicker().RemoveTicker(TickHandle); // 从核心Ticker移除Tick委托
}

/**
 * 每帧调用的Tick函数
 * @param DeltaTime 帧间隔时间
 * @return 总是返回true以持续接收Tick
 */
bool ULyraUIManagerSubsystem::Tick(float DeltaTime)
{
	SyncRootLayoutVisibilityToShowHUD(); // 调用同步根布局可见性函数
	
	return true; // 返回true确保持续Tick
}

/**
 * 同步根布局的可见性到HUD的显示状态
 */
void ULyraUIManagerSubsystem::SyncRootLayoutVisibilityToShowHUD()
{
	if (const UGameUIPolicy* Policy = GetCurrentUIPolicy()) // 获取当前UI策略
	{
		for (const ULocalPlayer* LocalPlayer : GetGameInstance()->GetLocalPlayers()) // 遍历所有本地玩家
		{
			bool bShouldShowUI = true; // 默认应该显示UI
			
			if (const APlayerController* PC = LocalPlayer->GetPlayerController(GetWorld())) // 获取玩家控制器
			{
				const AHUD* HUD = PC->GetHUD(); // 获取HUD

				if (HUD && !HUD->bShowHUD) // 如果HUD存在且不显示HUD
				{
					bShouldShowUI = false; // 则不应该显示UI
				}
			}

			if (UPrimaryGameLayout* RootLayout = Policy->GetRootLayout(CastChecked<UCommonLocalPlayer>(LocalPlayer))) // 获取根布局
			{
				const ESlateVisibility DesiredVisibility = bShouldShowUI ? ESlateVisibility::SelfHitTestInvisible : ESlateVisibility::Collapsed; // 根据条件计算期望的可见性
				if (DesiredVisibility != RootLayout->GetVisibility()) // 如果当前可见性与期望不符
				{
					RootLayout->SetVisibility(DesiredVisibility);	// 设置根布局为期望的可见性
				}
			}
		}
	}
}